/*
 *  画布引擎
 */
import { Topology } from '@topology/core';
import { canvasRegister } from './Register';

export interface IEngine {
  id: string;
  compute: () => any;
  // onMessage: onMessage,
  example: any;
}

interface IcanvasType extends Topology {
  [key: string]: any;
}

export class Engine {
  canvas: any | IcanvasType = {}; //画布

  id: string = '';

  example: any = null;

  canvasOptions: Record<string, any> = {
    // 画布配置
    rotateCursor: '/rotate.cur',
    locked: 2,
    grid: true,
    ruleColor: '#2db7f5',
    disableEmptyLine: true,
    disableScale: true,
  };

  /* 选中的节点 */
  targetNode: Record<string, any> = {};

  compute: any = () => {};

  scale: number | string = 1;

  constructor(props: IEngine) {
    this.init(props); // 初始化画布
  }

  init(props: IEngine) {
    this.id = props.id;
    this.compute = props.compute;
    this.canvasOptions.on = this.onMessage.bind(this);
    this.example = props.example;
  }

  /* 初始化Canvas 加载canvas布局*/
  initCanvas() {
    canvasRegister(); // 注册画布组件

    this.canvas = new Topology(this.id, this.canvasOptions);

    if (this.example) {
      this.example(this.example);
    }
  }

  canvasOpen(example: any) {
    if (example) {
    }
  }

  onMessage(event: string, data: any) {
    switch (event) {
      case 'node':
        this.targetNode = {
          node: data,
          line: null,
          multi: false,
          nodes: null,
          locked: data.locked,
        };
        return this?.compute();
      case 'addNode':
        this.targetNode = {
          node: data,
          line: null,
          multi: false,
          nodes: null,
          locked: data.locked,
        };
        return this?.compute();
      case 'addLine':
        this.targetNode = {
          node: null,
          line: data,
          multi: false,
          nodes: null,
          locked: data.locked,
        };
        return this?.compute();
      case 'line':
        this.targetNode = {
          node: null,
          line: data,
          multi: false,
          nodes: null,
          locked: data.locked,
        };
        return this?.compute();
      case 'space':
        this.targetNode = {
          node: null,
          line: null,
          multi: false,
          nodes: null,
          locked: null,
        };
        return this?.compute();
      default:
        break;
    }
  }

  /* 设置画布选中的节点 */
  setTargetNode(node: any) {
    this.targetNode = {
      node,
    };
  }

  /* 侦听屏幕大小改变 */
  onResize(width?: number, height?: number) {
    if (width && height && this.canvas) {
      this?.canvas?.resize({
        width,
        height,
      });
      this.onMouseReset();
    }
  }

  /* 更新node节点（updateProps） */
  updateNode(targetColor: Record<string, any>) {
    let targetNode = this.targetNode?.node;
    let [[key, color]] = Object.entries(targetColor);
    targetNode[key] = color;
    this.canvas?.updateProps(targetNode);
  }

  /* 更新线line */
  updateLine(lineProps: Object) {
    let targetLine = this.targetNode?.line;

    let [[key, lineType]] = Object.entries(lineProps);

    targetLine[key] = lineType;

    this.canvas?.updateProps(targetLine);
  }

  /* 更新node,自定义数据 */
  updateNodeData(data: Record<string, any>) {
    let targetNode = this.targetNode?.node;
    targetNode.data.valueObj = data;
    targetNode['text'] = data?.text;
    this.canvas?.updateProps(targetNode);
  }

  /* 解决鼠标错位 */
  onMouseReset() {
    this.canvas.canvasPos = this.canvas?.divLayer.canvas.getBoundingClientRect();
  }

  /* 撤销 */
  undo() {
    this.canvas?.undo();
  }

  /* 返回 */
  redo() {
    this.canvas?.redo();
  }

  /* 复制 */
  copy() {
    this.canvas?.copy();
  }

  /* 粘贴 */
  paste() {
    this.canvas?.paste();
  }

  /* 缩放 */
  scaleTo(type: 'in' | 'out' | 'reset') {
    let scale = this.canvas?.data.scale;

    let newScale: number = 0;

    if (type === 'in' && scale) {
      newScale = scale + 0.1;
    }

    if (type === 'out' && scale) {
      newScale = scale - 0.1;
    }

    if (type === 'reset' && scale) {
      newScale = 1;
    }

    this.scale = newScale;
    this.canvas?.scaleTo(newScale);
    this?.compute();
  }
}
